home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / awe2-0_1.lha / awe2-0.1 / Src / HardwareContext-mips.cc < prev    next >
C/C++ Source or Header  |  1990-07-09  |  7KB  |  227 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. // 
  3. // Copyright (C) 1988 University of Illinois, Urbana, Illinois
  4. // Copyright (C) 1989 University of Colorado, Boulder, Colorado
  5. // Copyright (C) 1990 University of Colorado, Boulder, Colorado
  6. //
  7. // written by Dirk Grunwald (grunwald@foobar.colorado.edu)
  8. //
  9. #include "HardwareContext.h"
  10. #include "HardwareContextP.h"
  11. #include "CpuMultiplexor.h"
  12. #include "Thread.h"
  13. #include "assert.h"
  14. #include <stream.h>
  15.  
  16. //
  17. //    Many machines have the same (or very similar) stack format.
  18. //    The 68K & 32K are examples of such machines.
  19. //
  20. //    The const *registers* defines the number of additional longwords
  21. //    needed on the stack past the last frame pointer. This value needs
  22. //    to jibe with the one in HardwareContext-<arch>.s.
  23. //
  24.  
  25. long MagicStackMarker = 0x464f4f20;    // this says 'FOO '
  26.  
  27. #define ALL_REGISTERS \
  28. asm (" " : : :\
  29.      "$0", "at", "v0", "v1",\
  30.      "a0", "a1", "a2", "a3", \
  31.      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",\
  32.      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",\
  33.      "t8", "t9",\
  34.      "k0", "k1", "gp", "sp", "fp", "ra",\
  35.      "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",\
  36.      "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",\
  37.      "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",\
  38.      "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" );\
  39.  
  40.  
  41. static int expectedBytesSavedInContext = 112;
  42. static int numberOfBytesSavedInContext = 0;
  43. static int numberOfQuadsSavedInContext = 0;
  44.  
  45. HardwareContext::HardwareContext (int check, unsigned size)
  46. {
  47.     checkStackLimits = check;
  48.  
  49.     stackBase = 0;
  50.     stackEnd = 0;
  51.     stackMax = 0;
  52.     stackSize = 0;
  53.     stackCheck = 0;
  54.     stackMallocAt = 0;
  55.  
  56.     if (size > 0) {
  57.     stackSize = size;
  58.     stackMallocAt = new void *[ stackSize ];
  59.     //
  60.     // stackBase should point to the first writeable cell of the
  61.     // new stack.
  62.     //
  63.     stackEnd = stackMallocAt;
  64.     stackBase = &stackMallocAt[stackSize-1];
  65.     }
  66.     else {
  67.     //
  68.     // Have the main process figure out how many registers
  69.     // (actually, Quads) are pushed when we save an entire context.
  70.     // Do this by calling magicSwitchTo with itself. This has
  71.     // the side-effect of storing fp & sp in the context.
  72.     //
  73.     magicSwitchTo(this);
  74.     numberOfBytesSavedInContext = (long) fp - (long) sp;
  75.     if ( numberOfBytesSavedInContext != expectedBytesSavedInContext ){
  76.         cerr << "error: " << __FILE__ << ", line " << int(__LINE__) << "\n";
  77.         cerr << "numberOfBytesSavedInContext = " << int(numberOfBytesSavedInContext) << "\n";
  78.         cerr << "expectedBytesSavedInContext = " << int(expectedBytesSavedInContext) << "\n";
  79.         exit(1);
  80.     }
  81.     numberOfQuadsSavedInContext = numberOfBytesSavedInContext / 4;
  82.  
  83.     //
  84.     // to make stack checks work
  85.     //
  86.  
  87.     stackCheck = &MagicStackMarker;
  88.     stackSize = 0xffffffff;
  89.     }
  90. }
  91.  
  92. void
  93. HardwareContext::reclaimStack()
  94. {
  95.     if ( stackMallocAt ) {
  96.     free(stackMallocAt);
  97.     stackMallocAt = 0;
  98.     }
  99. }
  100.  
  101. void
  102. HardwareContext::magicSwitchTo(HardwareContext *to)
  103. {
  104.     ALL_REGISTERS;
  105.     asm("    sw    $29,%0" : : "m" (sp));
  106.     asm("    sw    $30,%0" : : "m" (fp));
  107.     asm("    lw    $29,%0" : "=g" (to -> sp));
  108.     asm("    lw    $30,%0" : "=g" (to -> fp));
  109. }
  110.  
  111. void
  112. HardwareContext::stackOverflow()
  113. {
  114.     register unsigned depth = stackBase - getSp();
  115.     if (stackMax < depth) {
  116.     stackMax = depth;
  117.     }
  118.     if ( stackMax >= stackSize ) {
  119.     cerr << "\nStack overflow\n";
  120.     cerr << " getSp() = " << hex(long(getSp()));
  121.     cerr << " and stackBase = " << hex(long(stackBase)) << "\n";
  122.     cerr << *this << "\n";
  123.     cerr << "Current task is \n";
  124.     cerr << *(CurrentThread());
  125.     cerr << "\n";
  126.     cerr.flush();
  127.     }
  128.     assert( stackMax < stackSize );
  129.     assert( *stackCheck == MagicStackMarker );
  130. }
  131.  
  132. //
  133. //    Unlike other architectures, the MIPS processor passes arguments
  134. //    in registers. Thus, startOff will assume that *this* is stored
  135. //    in $a0 -- this may not be true, because we're not causing a0,etc
  136. //    to be saved & restored. In general, compilers may save/restore
  137. //    the argument registers in other registers. Hence, this hack.
  138. //
  139. //    We have the new thread return to __magicReturnFunction with four
  140. //    arguments explicitly stored in the stack. We load the first of these
  141. //    two arguments, which is the value of *this* to be passed to the
  142. //    function addressed in the second argument. Clear?
  143. //
  144. extern "C" {
  145.  void __magicReturnFunction();
  146. };
  147.  
  148. asm("    .ent    __magicReturnFunction");
  149. asm("    .globl    __magicReturnFunction");
  150. asm("__magicReturnFunction:");
  151. asm("    lw    $4,0($30)");
  152. asm("    lw    $31,4($30)");
  153. asm("    j    $31");
  154. asm("    .end    __magicReturnFunction");
  155.  
  156. void
  157. HardwareContext::buildReturnFrame(void *returnThis, voidFuncP returnAddress)
  158. {
  159.     //
  160.     //    To build a thread, we return to the first address of startOff,
  161.     //    which will use the current FP & SP to build a local context,
  162.     //    and then call the user main.
  163.     //
  164.     //    startOff needs to have a valid frame. The return address for this
  165.     //    frame is NULL, since we never exit procedure startOff.
  166.     //
  167.     
  168.     stackCheck = (long *) stackBase;
  169.     register HardwareContextQuad **stack;
  170.     stack = (HardwareContextQuad **) stackBase;
  171.     HardwareContextQuad **FP[4];
  172.     HardwareContextQuad **SP[4];
  173.  
  174.     /////////////// FIRST FRAME
  175.     // space for four args
  176.     FP[0] = stack;
  177.     stack -= 2;
  178.     stackCheck = (long *) stack;
  179.     *(stack--) = (HardwareContextQuad *) MagicStackMarker;
  180.     SP[0] = stack;
  181.     *(stack--) = 0;            // return address
  182.  
  183.     // provide space for four args a0..a4 and put
  184.     // return address in space for a1, and this for that fcn
  185.     // in a0. __magicReturnFunction will read these from the stack
  186.     // and jump to the return address with *this* set properly.
  187.  
  188.     stack -= 2;
  189.     *(stack--) = (HardwareContextQuad *) returnAddress;
  190.     *(stack) = (HardwareContextQuad *) returnThis;
  191.  
  192.     /////////////// SECOND FRAME
  193.     FP[1] = stack;
  194.     stack -= (numberOfQuadsSavedInContext-1);    // leave space for ....
  195.     *(stack--) = (HardwareContextQuad *) FP[1];
  196.     *(stack) = (HardwareContextQuad *) __magicReturnFunction;
  197.     SP[1] = stack;
  198.  
  199.     fp = (HardwareContextQuad) FP[1];
  200.     sp = (HardwareContextQuad) SP[1];
  201.  
  202. #ifdef DEBUG
  203.     cerr << "[HardwareContext-mips] Build stack for " << hex(long(this)) << "\n";
  204.     cerr << "[HardwareContext-mips] FP[0] = " << hex(long(FP[0])) << "\n";
  205.     cerr << "[HardwareContext-mips] SP[0] = " << hex(long(SP[0])) << "\n";
  206.     cerr << "[HardwareContext-mips] FP[1] = " << hex(long(FP[1])) << "\n";
  207.     cerr << "[HardwareContext-mips] SP[1] = " << hex(long(SP[1])) << "\n";
  208. #endif
  209. }
  210.  
  211. void
  212. HardwareContext::classPrintOn(ostream& s)
  213. {
  214.     s << "[HardwareContext] Stack spans " << hex(long(stackEnd));
  215.     s << " to " << hex(long(stackBase));
  216.     s << " used is  " << (stackMax) << " of " << stackSize << "\n";
  217.     s << "[HardwareContext] fp = " << hex(long(fp));
  218.     s << " sp = " << hex(long(sp));
  219.     long p = *( (long *) fp );
  220.     s << " @fp = " << hex(p) << "\n";
  221. }
  222.  
  223. static
  224. void PrintSingleStackFrame()
  225. {
  226. }
  227.